﻿using System;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
using System.Windows.Forms;
using System.Xml.XPath;
using System.Xml.Xsl;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.TextManager.Interop;
using Wicresoft.Shell.Core;

namespace Wicresoft.XslDebugger
{
    /// <summary>
    /// Summary description for MyControl.
    /// </summary>
    public partial class MyControl : UserControl, IVsRunningDocTableEvents
    {
        protected uint _rdtEventCookie;
        protected MyToolWindow _parent;
        protected IVsTextView _textView = null;

        public MyControl(MyToolWindow parent)
        {
            InitializeComponent();

            _parent = parent;

            // Tell RDT I can handle RunningDocTableEvents
            IVsRunningDocumentTable rdt = GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
            rdt.AdviseRunningDocTableEvents(this, out _rdtEventCookie);

            // Get access to the current active text view, using _textView to refer it.
            IVsTextView textView = null;
            IVsTextManager textManager = GetService(typeof(SVsTextManager)) as IVsTextManager;
            textManager.GetActiveView(1, null, out textView);
            HandleTextViewChange(textView);
        }

        #region IVsRunningDocTableEvents Members

        public int OnAfterAttributeChange(uint docCookie, uint grfAttribs)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        // When current window in VS is changed, this method will be called.
        public int OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame)
        {
            HandleTextViewChange(null);

            return 0;
        }

        public int OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public int OnAfterSave(uint docCookie)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        // When current window in VS is changed, this method will be called.
        public int OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
        {
            IntPtr pCodeWindow;
            Guid riid = typeof(IVsCodeWindow).GUID;

            pFrame.QueryViewInterface(ref riid, out pCodeWindow);
            if (pCodeWindow.ToInt32() == 0)
            {
                HandleTextViewChange(null);
                return 0;
            }

            IVsCodeWindow codeWindow = (IVsCodeWindow)Marshal.GetObjectForIUnknown(pCodeWindow);

            IVsTextView textView;
            codeWindow.GetPrimaryView(out textView);

            HandleTextViewChange(textView);

            return 0;
        }

        public int OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region protected or private methods

        protected void HandleTextViewChange(IVsTextView textView)
        {
            _textView = textView;
        }

        protected override object GetService(Type service)
        {
            object obj = null;
            if (_parent != null)
            {
                obj = _parent.GetVsService(service);
            }
            if (obj == null)
            {
                obj = base.GetService(service);
            }
            return obj;
        }

        private string Transform(string source, string xsl)
        {
            StringReader htmlReader = new StringReader(source);
            XPathDocument htmlDocument = new XPathDocument(htmlReader);

            StringReader xslReader = new StringReader(xsl);
            XPathDocument xslDocument = new XPathDocument(xslReader);

            StringBuilder resultStringBuilder = new StringBuilder();
            StringWriter resultStringWriter = new StringWriter(resultStringBuilder);
            XslCompiledTransform xslTransform = new XslCompiledTransform();
            //XslTransform xslTransform = new XslTransform();
            xslTransform.Load(xslDocument);
            xslTransform.Transform(htmlDocument, null, resultStringWriter);
            return resultStringBuilder.ToString();
        }

        #endregion

        #region event handlers

        public void SetHtmlString(String htmlStr)
        {
            txtHtml.Text = htmlStr;
        }

        public void tsbtnLoadHtml_Click(object sender, System.EventArgs e)
        {
            try
            {
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    txtHtml.Text = File.ReadAllText(openFileDialog1.FileName);
                }
            }
            catch (Exception ex)
            {
                Logger.Output("Error(" + ex.GetType().ToString() + "): " + ex.Message);
            }
        }

        public void tsbtnTransform_Click(object sender, System.EventArgs e)
        {
            try
            {
                if (_textView != null)
                {
                    // Get line count and column count
                    IVsTextLines textLines;
                    _textView.GetBuffer(out textLines);
                    int lineCount;
                    textLines.GetLineCount(out lineCount);
                    int columnCount = 0;
                    for (int i = 0; i < lineCount; i++)
                    {
                        int currentColumnCount;
                        textLines.GetLengthOfLine(i, out currentColumnCount);
                        if (currentColumnCount > columnCount) columnCount = currentColumnCount;
                    }

                    // Get the text
                    string text;
                    _textView.GetTextStream(0, 0, lineCount - 1, columnCount - 1, out text);
                    if (string.IsNullOrEmpty(text))
                    {
                        Logger.Output("Error: 当前活动的文件不能为空。");
                        return;
                    }
                    txtUMC.Text = Transform(txtHtml.Text, text);
                }
            }
            catch (Exception ex)
            {
                Logger.Output("Error(" + ex.GetType().ToString() + "): " + ex.Message,WriteTo.OutputWindow);
            }
        }

        private void txtHtml_KeyDown(object sender, KeyEventArgs e)
        {
            // ctrl + A to select all.
            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
            {
                TextBox textBox = sender as TextBox;
                if (textBox != null)
                {
                    textBox.SelectAll();
                }
            }
        }

        #endregion
    }
}
